package org.erepublik.company.charts;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import org.erepublik.company.searchCriteria.EFoodSearchCriteria;
import org.erepublik.company.searchCriteria.EHouseChartCriteria;
import org.erepublik.company.searchCriteria.EMovingDistance;
import org.erepublik.company.searchCriteria.EWeaponChartCriteria;
import org.erepublik.company.utils.Utils;

@Entity
public class ChartDataSet {

	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE)
	private int id;

	@OneToMany(mappedBy = "dataSet", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	private List<ChartData> data;
	private long lastDataSet;
	private String country;
	private String resourceName;
	private String attribute;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public List<ChartData> getData() {
		return data;
	}

	public void setData(List<ChartData> data) {
		this.data = data;
	}

	public long getLastDataSet() {
		return lastDataSet;
	}

	public void setLastDataSet(long lastDataSet) {
		this.lastDataSet = lastDataSet;
	}

	public String getAttribute() {
		return attribute;
	}

	public void setAttribute(String attribute) {
		this.attribute = attribute;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public String getCountry() {
		return country;
	}

	public void setResourceName(String resourceName) {
		this.resourceName = resourceName;
	}

	public String getResourceName() {
		return resourceName;
	}

    public double getTodayPrice() {
        int size = getData().size();
        if (size==0)
            return 0;
        return getData().get(size-1).getValue();
    }

    public double getYesterdayPrice() {
        long yesterday = new Date().getTime() - 1000l*60l*60l*24l;
        int size = getData().size();
        for (int i=size-1; i > 0; i--) {
            long time = getData().get(i).getTime();
            if (time < yesterday)
                return getData().get(i).getValue();
        }
        return 0.0d;
    }

    public double getWeekAgoPrice() {
        long yesterday = new Date().getTime() - 1000l*60l*60l*24l*7l;
        int size = getData().size();
        for (int i=size-1; i > 0; i--) {
            long time = getData().get(i).getTime();
            if (time < yesterday)
                return getData().get(i).getValue();
        }
        return 0.0d;
    }
    
 

    
    
    
    @SuppressWarnings("deprecation")
    private ArrayList<String> getLast24hoursAsGoogleChart() {
        long today = new Date().getTime();
        ArrayList<String> dates = new ArrayList<String>();
        for (int i=5; i >= 0; i--) {
            Date date = new Date(today - i*1000*60*60*4);
            dates.add(date.getHours()+":"+ date.getMinutes());
        }
        return dates;
    }

  
    
    @SuppressWarnings("unchecked")
    public String getGoogleChartFor2months(Enum atribute, String country) {
        final int DATA_SIZE=50;
        ArrayList<ChartData> filteredData = new ArrayList<ChartData>();
        ArrayList<ChartData> weekData = new ArrayList<ChartData>();
        long weekAgo = new Date().getTime() - 1000l*60l*60l*24l*7l*8l;
        for (int i=0; i < getData().size(); i++) {
            if ( getData().get(i).getTime()>weekAgo )
                weekData.add( getData().get(i) );
        }
        
        int dataSize = weekData.size();
        for (int i=0; i < dataSize; i++) {
            double niewiemjaknazwac = (i/(double)dataSize)*DATA_SIZE;
            if (niewiemjaknazwac>=filteredData.size()) {
                filteredData.add( weekData.get(i) );
            }
        }
        

        
        return getDataForGoogleChart(new Date().getTime()-1000l*60l*60l*24l*7l*8l,600, 300, filteredData, getLast2monthsAsGoogleChart(), 
                getTitle(atribute)+"|Price history for the last 2 months|"+country);
    }
    
    
    @SuppressWarnings("unchecked")
    private String getTitle(Enum atribute) {
        String title = "";
        if (atribute instanceof EFoodSearchCriteria)
            title = ((EFoodSearchCriteria)atribute).getName()+" restored  with food for 1 gold";
        if (atribute instanceof EMovingDistance)
            title = "price of "+((EMovingDistance)atribute).getDistance()+" zone ticket in gold";
        if (atribute instanceof EHouseChartCriteria)
            title = "wellness restored  with house for 1 gold";
        if (atribute instanceof EWeaponChartCriteria)
            title = "Price for Q5 weapon ";
        return title;
    }
    
    


    @SuppressWarnings("unchecked")
    public String getGoogleChartFor7days(Enum atribute, String country) {
        final int DATA_SIZE=50;
        ArrayList<ChartData> filteredData = new ArrayList<ChartData>();
        ArrayList<ChartData> weekData = new ArrayList<ChartData>();
        long weekAgo = new Date().getTime() - 1000*60*60*24*7;
        for (int i=0; i < getData().size(); i++) {
            if ( getData().get(i).getTime()>weekAgo )
                weekData.add( getData().get(i) );
        }
        
        int dataSize = weekData.size();
        for (int i=0; i < dataSize; i++) {
            double niewiemjaknazwac = (i/(double)dataSize)*DATA_SIZE;
            if (niewiemjaknazwac>=filteredData.size()) {
                filteredData.add( weekData.get(i) );
            }
        }
        
        
        return getDataForGoogleChart(new Date().getTime()-1000l*60l*60l*24l*7l, 600, 300, filteredData, getLast7daysAsGoogleChart(), 
                getTitle(atribute)+"|Price history for the last 7 days|"+country);
    }
    
    
    
    @SuppressWarnings("unchecked")
    public String getGoogleChartFor24hours(Enum atribute, String country) {
        final int DATA_SIZE=50;
        ArrayList<ChartData> filteredData = new ArrayList<ChartData>();
        ArrayList<ChartData> weekData = new ArrayList<ChartData>();
        long weekAgo = new Date().getTime() - 1000*60*60*24;
        for (int i=0; i < getData().size(); i++) {
            if ( getData().get(i).getTime()>weekAgo )
                weekData.add( getData().get(i) );
        }
        
        int dataSize = weekData.size();
        for (int i=0; i < dataSize; i++) {
            double niewiemjaknazwac = (i/(double)dataSize)*DATA_SIZE;
            if (niewiemjaknazwac>=filteredData.size()) {
                filteredData.add( weekData.get(i) );
            }
        }
        
        
        
        return getDataForGoogleChart(new Date().getTime()-1000l*60l*60l*24l, 600, 300, filteredData, getLast24hoursAsGoogleChart(), 
                getTitle(atribute)+"|Price history for the last 24 hours|"+country);
    }    
    
    
    
    private String getDataForGoogleChart(long startTime, int width, int height, ArrayList<ChartData> data, ArrayList<String> xLabels, String title) {
    
	ChartData[] sortedData = data.toArray(new ChartData[0]);
	Arrays.sort(sortedData);
	data = new ArrayList<ChartData>();
	for (ChartData chartData : sortedData) {
		data.add(chartData);
	}
	    
        double maxPrice=0;
        for (int i=0; i < data.size(); i++) {
            if (maxPrice<data.get(i).getValue())
                maxPrice = data.get(i).getValue();
        }
        if (maxPrice>=100)
            maxPrice = Math.ceil(maxPrice/100)*100;
        
        long firstData = startTime;
        long lastData = new Date().getTime();
        long timeLength = lastData - firstData;
        
        int[] x = new int[data.size()];
        int[] y = new int[data.size()];
        for (int i=0; i < x.length; i++) {
            x[i] = (int)(((data.get(i).getTime() - firstData)/(double)timeLength ) * 100);
            y[i] = (int)((data.get(i).getValue()/maxPrice ) * 100);
        }
        
        StringBuffer str = new StringBuffer("http://chart.apis.google.com/chart?");
        str.append("cht=lxy");
        str.append("&chd=t:");
        for (int i=0; i < x.length; i++) {
            if (i!=0)
                str.append(",");
            str.append(x[i]);
        }
        str.append("|");
        for (int i=0; i < y.length; i++) {
            if (i!=0)
                str.append(",");
            str.append(y[i]);
        }
        str.append("&chs=600x300");
        str.append("&chco=FF0000");
        str.append("&chxt=x,y");
        str.append("&chxr=1,0,"+Utils.round(maxPrice,3));
        str.append("&chxl=0:");
        for (int i=0; i < xLabels.size(); i++) {
            str.append("|");
            str.append(xLabels.get(i));
        }
            
        str.append("&chf=c,lg,0,FFE7C6,0,76A4FB,1");
        str.append("&chtt="+title);
        
        double przedzialki = Utils.round( 10000.0d/maxPrice,2 );
        if (maxPrice<100)
            przedzialki=10.0d;
        
        str.append("&chg="+Utils.round( 100.0d/(xLabels.size()-1),2 )+","+( przedzialki ) );
  
        return str.toString();
    }
    
    @SuppressWarnings("deprecation")
    private ArrayList<String> getLast7daysAsGoogleChart() {
        long today = new Date().getTime();
        ArrayList<String> dates = new ArrayList<String>();
        for (int i=6; i >= 0; i--) {
            Date date = new Date(today - i*1000l*60l*60l*24l);
            dates.add(date.getDate()+"."+ toRomanian(date.getMonth()) );
        }

        return dates;
    }
    
    
    private ArrayList<String> getLast2monthsAsGoogleChart() {
        ArrayList<String> dates = new ArrayList<String>();

        for (int i=7; i >= 2; i--) {
            dates.add( i + "weeks ago" );
        }
        dates.add("1 week ago");
        dates.add("now");
        return dates;
    }
    
    
    
    
    
    
    

    private String toRomanian(int month) {
        if (month==0)
            return "I";
        if (month==1)
            return "II";        
        if (month==2)
            return "III";     
        if (month==3)
            return "IV";           
        if (month==4)
            return "V";       
        if (month==5)
            return "VI";     
        if (month==6)
            return "VII";            
        if (month==7)
            return "VIII";             
        if (month==8)
            return "IX";               
        if (month==9)
            return "X";    
        if (month==10)
            return "XI";   
        if (month==11)
            return "XII";   
        
        
        return null;
    }
    

}
